'''
Created on 2012-12-21

@author: levi
'''

import pydot
import datetime
from uuid import UUID

from core.himesis import HConstants as HC
from core.himesis import Himesis

from tc_python.arule import ARule
from tc_python.frule import FRule
from tc_python.lrule import LRule

from t_core.messages import Packet
from t_core.matcher import Matcher
from t_core.rewriter import Rewriter
from t_core.iterator import Iterator
from t_core.resolver import Resolver
from t_core.rollbacker import Rollbacker

from symbolic_state_space import SymbolicStateSpace

#from transformation_patterns.HS2S_clean import HS2S_clean
from transformation_patterns.HM2M import HM2M

from collapse_patterns_old.HTwoStations import HTwoStations
from collapse_patterns_old.HOneStation import HOneStation

from symbolic_exec_patterns.HBuild_backLHS import HBuild_backLHS
from symbolic_exec_patterns.HBuild_backRHS import HBuild_backRHS

from collapse_patterns_old.HFindTwoStationsLHS import HFindTwoStationsLHS
from collapse_patterns_old.HMoveOneOutputLinkLHS import HMoveOneOutputLinkLHS
from collapse_patterns_old.HMoveOneOutputLinkRHS import HMoveOneOutputLinkRHS
from collapse_patterns_old.HMoveOneInputLinkLHS import HMoveOneInputLinkLHS
from collapse_patterns_old.HMoveOneInputLinkRHS import HMoveOneInputLinkRHS
from collapse_patterns_old.HEraseDisconnectedStationRHS import HEraseDisconnectedStationRHS
from collapse_patterns_old.HEraseDisconnectedStationLHS import HEraseDisconnectedStationLHS
from collapse_patterns_old.HCheckStationInNeighborsLHS import HCheckStationInNeighborsLHS
from collapse_patterns_old.HCheckStationOutNeighborsLHS import HCheckStationOutNeighborsLHS
from collapse_patterns_old.HMoveOneOutputLink2LHS import HMoveOneOutputLink2LHS
from collapse_patterns_old.HMoveOneOutputLink2RHS import HMoveOneOutputLink2RHS
from collapse_patterns_old.HMoveOneInputLink2LHS import HMoveOneInputLink2LHS
from collapse_patterns_old.HMoveOneInputLink2RHS import HMoveOneInputLink2RHS
from collapse_patterns_old.HDeleteStationLHS import HDeleteStationLHS
from collapse_patterns_old.HDeleteStationRHS import HDeleteStationRHS

from collapse_with_backward_patterns.HFindTwoMatchElementsWithBackwardLHS import HFindTwoMatchElementsWithBackwardLHS


from copy import deepcopy

def graph_to_dot(name, g):
    vattr=''
    eattr = ''
    nodes = {}
    graph = pydot.Dot(name, graph_type='digraph')
    dateTag = datetime.datetime.now().strftime("%Y-%b-%d_%H-%M-%S")
    for v in g.vs:
        vattr += str(v['name'])                                                                                                                                                                                     
        vattr += ' < '
        vattr += str(v['mm__']) 
        vattr += ' < '        
        vattr += str(v['GUID__'])[-12:]
        print vattr     
        nodes[v.index] = pydot.Node(vattr)
        graph.add_node(nodes[v.index])
        vattr = ''
    for e in g.es:
        graph.add_edge(pydot.Edge(nodes[e.source],nodes[e.target]))
#    graph.write('/home/levi/Desktop/STATE%s%s.svg'%(key,dateTag))    
    graph.write('/home/levi/Desktop/%s.dot'%name)
    
    
def merge_models(first, second):
    nb_nodes_first = len(first.vs)
    for index_v in range(len(second.vs)):
        first.add_node()
        first.vs[nb_nodes_first + index_v]['mm__'] = second.vs[index_v]['mm__']   
        first.vs[nb_nodes_first + index_v]['name'] = second.vs[index_v]['name'] 
    for index_e in range(len(second.es)):
        first.add_edges((nb_nodes_first + second.es[index_e].tuple[0],nb_nodes_first + second.es[index_e].tuple[1]))
    return first


def eliminate_repeated_collapse_matches(match_set):
    new_match_set = []
    for i in range(0, len(match_set)):
        found_repeated = False
        for j in range(0, i):
            if match_set[i]['1'] == match_set[j]['2'] and match_set[i]['2'] == match_set[j]['1']:
                found_repeated = True
                break
        if not found_repeated:
            new_match_set.append(match_set[i])
    return new_match_set

    
def collapse(p, index):
    
#    graph_to_dot('out' + str(index), p.graph)
    
    i = Iterator()
    r = Rollbacker(HFindTwoMatchElementsWithBackwardLHS())
    p = m.packet_in(p)
    
    print m.is_success  

    if m.is_success:

#        print 'Before:'
#        print p.match_sets[p.current].matches
        p.match_sets[p.current].matches = eliminate_repeated_collapse_matches(p.match_sets[p.current].matches)
#        print 'After:'
#        print p.match_sets[p.current].matches        
#        print '------------------------------------'     
        
        p = i.packet_in(p)     
        p = r.packet_in(p)             

        while True:
            
            print '-----> Depth: ' + str(index)
            print p
            print p.match_sets[p.current].match2rewrite
    
            # perform one collapse step
            p = rin.packet_in(p)
            p = rout.packet_in(p)
            p = erase.packet_in(p)    
            
            graph_to_dot('out' + str(index) + '.' + str(i.iterations), p.graph)
            
            p1 = Packet()
            p1.graph = deepcopy(p.graph)
            
            # collapse the remaining graph   
            collapse(p1, index+1)            
    
            # get back the graph previously to the collapse step
            p = r.next_in(p)
            # iterate to the next two elements to collapse
            p = i.next_in(p)
            if not i.is_success:
                return True
            
 #           print p

            # save the state of the iterator before collapsing
            p = r.packet_in(p)
        
    else:
        return False


def collapse_backward(p, index):
    
#    graph_to_dot('out' + str(index), p.graph)
    
    i = Iterator()
    r = Rollbacker(HFindTwoStationsLHS())
    p = m_back.packet_in(p)
    
    print m.is_success  

    if m.is_success:

#        print 'Before:'
#        print p.match_sets[p.current].matches
        p.match_sets[p.current].matches = eliminate_repeated_collapse_matches(p.match_sets[p.current].matches)
#        print 'After:'
#        print p.match_sets[p.current].matches        
#        print '------------------------------------'     
        
        p = i.packet_in(p)     
        p = r.packet_in(p)             

        while True:
            
            print '-----> Depth: ' + str(index)
            print p
            print p.match_sets[p.current].match2rewrite
    
            # perform one collapse step
            p = rin.packet_in(p)
            p = rout.packet_in(p)
            p = erase.packet_in(p)    
            
            graph_to_dot('out' + str(index) + '.' + str(i.iterations), p.graph)
            
            p1 = Packet()
            p1.graph = deepcopy(p.graph)
            
            # collapse the remaining graph   
            collapse(p1, index+1)            
    
            # get back the graph previously to the collapse step
            p = r.next_in(p)
            # iterate to the next two elements to collapse
            p = i.next_in(p)
            if not i.is_success:
                return True
            
 #           print p

            # save the state of the iterator before collapsing
            p = r.packet_in(p)
        
    else:
        return False
    

if __name__ == '__main__':                                                                                                                              
    pass

                                                                                                                                                                                        
m = Matcher(HFindTwoStationsLHS())
m_back = Matcher(HFindTwoMatchElementsWithBackwardLHS())

rout = FRule(HMoveOneOutputLinkLHS(), HMoveOneOutputLinkRHS())
rin = FRule(HMoveOneInputLinkLHS(), HMoveOneInputLinkRHS())
erase = FRule(HDeleteStationLHS(), HDeleteStationRHS())

matchStation = Matcher(HEraseDisconnectedStationLHS())
eraseStation = Rewriter(HEraseDisconnectedStationRHS())
checkInNeighbors = Matcher(HCheckStationInNeighborsLHS())
checkOutNeighbors = Matcher(HCheckStationOutNeighborsLHS())

moveOutLinks = FRule(HMoveOneOutputLink2LHS(), HMoveOneOutputLink2RHS())
moveInLinks = FRule(HMoveOneInputLink2LHS(), HMoveOneInputLink2RHS())


#m = Matcher(HMoveOneOutputLinkLHS())
#r = Rewriter(HMoveOneOutputLinkRHS())
#x = Rollbacker(m.condition)
i = Iterator()
i2 = Iterator()
i3 = Iterator()

r = Rollbacker(HFindTwoStationsLHS())

p = Packet()
p.graph = HTwoStations()

#p = m.packet_in(p)
#print p.match_sets[p.current].matches
#l = eliminate_repeated_collapse_matches(p.match_sets[p.current].matches)
#print l
#graph_to_dot('source', p.graph)


#p = m.packet_in(p)
#p = i.packet_in(p)


'''
while True:

    p1 = deepcopy(p)
    p1 = rin.packet_in(p1)
    p1 = rout.packet_in(p1)
    
    del p1.global_pivots['station1']
    del p1.global_pivots['station2']     

    p1 = matchStation.packet_in(p1)
    
    print p1.global_pivots
    
    if matchStation.is_success:        
        p1 = i2.packet_in(p1)           
        while True:


            p2 = deepcopy(p1)  
            p3 = deepcopy(p1)              
            p2 = checkInNeighbors.packet_in(p2)
            if not checkInNeighbors.is_success:
                if checkInNeighbors.exception:
                    print checkInNeighbors.exception            
            foundInNeighbors = checkInNeighbors.is_success
            
            p3 = checkOutNeighbors.packet_in(p3)                 
            foundOutNeighbors = checkOutNeighbors.is_success
                
            print not(foundInNeighbors) and not(foundOutNeighbors)

            if not(foundInNeighbors) and not(foundOutNeighbors):            
                p1 = eraseStation.packet_in(p1)  
                print '---'

            p1 = i2.next_in(p1)
            if not i2.is_success:
                break
              
    graph_to_dot('out' + str(i.iterations), p1.graph)
              
    p = i.next_in(p)
    if not i.is_success:
        break
    print '>>>>'
'''

'''
    
while True:
    p1 = deepcopy(p)
    p1 = rin.packet_in(p1)
    p1 = rout.packet_in(p1)
    p1 = erase.packet_in(p1)    
    graph_to_dot('out' + str(i.iterations), p1.graph)
    
    p = i.next_in(p)
    if not i.is_success:
        break
    print '>>>>'
'''


''''
p = r.packet_in(p)

while True:
    
    p = rin.packet_in(p)
    p = rout.packet_in(p)
    p = erase.packet_in(p)    
    graph_to_dot('out' + str(i.iterations), p.graph)
    
    p = r.next_in(p)
    p = i.next_in(p)
    if not i.is_success:
        break
    print '>>>><<<<<'
    p = r.packet_in(p)
'''

#r = eliminate_repeated_collapse_matches([{'1': UUID('42685541-b6c0-422e-8271-af61b06eee9e'), '2': UUID('b597d80c-983f-43df-825e-8d22ab1807c4')}, {'1': UUID('b597d80c-983f-43df-825e-8d22ab1807c4'), '2': UUID('42685541-b6c0-422e-8271-af61b06eee9e')}])
#print r

graph_to_dot('source', p.graph)

collapse(p, 1)




   
    

    

#first = HTwoStations()
#second = HOneStation()
#
#first = merge_models(first, second)
#
#graph_to_dot('first', first)

#for v in second.vs:
#    print v

#second.add_node()
#
#second.vs[9]['mm__'] = 'Station_S'
#second.vs[9]['name'] = 's10'
#
#print second.vs[9]
#
#graph_to_dot('second', second)


#p = m.packet_in(p)
#print p.match_sets[p.current].match2rewrite
#
#p = i.packet_in(p)
#
#p1 = deepcopy(p)

#print p1.match_sets[p1.current].match2rewrite
#out1 = r.packet_in(p1)


#p = i.next_in(p)
#p2 = deepcopy(p)
#print p2.match_sets[p2.current].match2rewrite
#out2 = r.packet_in(p2)
#graph_to_dot('out20', out2.graph)

#p = i.next_in(p)
#print p.match_sets[p.current].match2rewrite
#out3 = r.packet_in(p)
#
#p = i.next_in(p)
#print p.match_sets[p.current].match2rewrite
#out4 = r.packet_in(p)
#
#p = i.next_in(p)
#print p.match_sets[p.current].match2rewrite
#out5 = r.packet_in(p)

#graph_to_dot('out1', out1.graph)
#graph_to_dot('out2', out2.graph)
#graph_to_dot('out3', out3.graph)
#graph_to_dot('out4', out4.graph)
#graph_to_dot('out5', out5.graph)

#while i.is_success == True:
#    print p
#    p = i.next_in(p)


#print p.match_sets[m.condition[HC.GUID]]
#print p.current
#print p.global_pivots



#while a.is_success == True:
#    p = a.packet_in(p)





#g = graph1
#for e in g.es:
#    print e.source

#graph_to_dot('source', HTwoStations())
#graph_to_dot('twostationscol3', p.graph)



#print graph1
#print graph2

#graph1.add_edges(graph2.get_edgelist())
#g = graph1.draw()

#g.save('/home/levi/Desktop/test.svg')

#f=FRule(HBuild_backLHS(),HBuild_backRHS())
#p = Packet()
#p.graph = HS2S_clean()
#print p
#p1 = f.packet_in(p)
#print p1